
/*
 * MIT License
 *
 * Copyright (c) 2023 芊芊墨客
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

package com.zhangmeng.tools.controller;

import com.zhangmeng.tools.config.Constants;
import com.zhangmeng.tools.utils.ImagePath;
import com.zhangmeng.tools.utils.ResourcesUtils;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.SplitPane;
import javafx.scene.control.cell.TextFieldListCell;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Arrays;

/**
 * @author : 芊芊墨客
 * @version : 1.0
 * @date : 2023-02-16 10:04
 */
@Slf4j
public class PlayerController {

    private SimpleDoubleProperty width = new SimpleDoubleProperty(0.0);
    private SimpleDoubleProperty height = new SimpleDoubleProperty(0.0);
    private AnchorPane root;

    private AnchorPane video;
    private AnchorPane music;
    private AnchorPane vip_parser;
    private AnchorPane music_parser;
    private AnchorPane video_transcoder;

    private MusicController musicController;
    private VideoController videoController;
    private MusicDownloadController musicDownloadController;
    private VideoTranscoderController videoTranscoderController;

    @FXML
    private ListView<ResourcesUtils.Player> listView;

    @FXML
    private SplitPane splitPane;

    public static final String color_cell = "#f4f4f4";

    public void close_current_page_init() {
//        if (video != null) {
//            MediaPlayer mp = videoController.getMp();
//            if (mp != null){
//               mp.stop();
//            }
//        }
//
//        if (music != null) {
//            MediaPlayer mp = musicController.getMp();
//            if (mp != null){
//                mp.stop();
//            }
//        }

        if (video != null) {
            MediaPlayer mp = videoController.getMp();
            if (mp != null) {
                mp.stop();
            }
        }

        if (music != null) {
            Constants.setRoot(Constants.Type.Music,music);
        }

        if (video_transcoder != null){
            Constants.setRoot(Constants.Type.VideoTranscoder,video_transcoder);
        }
    }

    @FXML
    public void md5_menu_item() {
        load_encrypt(1);
    }

    @FXML
    public void spring_security_menu_item() {
        load_encrypt(2);
    }

    @FXML
    private void hex_16_menu_item() {
        load_small_tools(0);
    }

    @FXML
    private void unicode_menu_item() {
        load_small_tools(1);
    }

    @FXML
    private void jwt_menu_item() {
        load_small_tools(2);
    }

    @FXML
    private void color_choose_menu_item() {
        load_small_tools(3);
    }

    @FXML
    private void qr_code_menu_item() {
        load_small_tools(4);
    }

    @FXML
    private void base_62_menu_item() {
        load_codec_tools(0);
    }

    @FXML
    private void base_64_menu_item() {
        load_codec_tools(1);
    }

    @FXML
    private void base_32_menu_item() {
        load_codec_tools(2);
    }

    @FXML
    private void morse_coder_menu_item() {
        load_codec_tools(3);
    }

    @FXML
    public void sql_code_gen_menu_item() {
        load_sql_tools(0);
    }

    @FXML
    public void video_menu_item() {
        boolean flag = false;
        if (video != null) {
            flag = true;
        }
        video(flag);
    }

    @FXML
    public void music_menu_item() {
        boolean flag = false;
        if (music != null) {
            flag = true;
        }
        music(flag);
    }

    @FXML
    public void vip_parser_menu_item() {
        boolean flag = false;
        if (vip_parser != null) {
            flag = true;
        }
        vip_parser(flag);
    }

    @FXML
    public void date_query_menu_item() {
        load_small_tools(5);
    }

    @FXML
    public void cron_menu_item() {
        load_small_tools(6);
    }

    @FXML
    public void netty_client_menu_item() {
        load_network_tools(6);
    }

    public void load_network_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("network-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void load_codec_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("codec-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void load_sql_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("sql-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void load_small_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("small-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }


    public void load_encrypt(int index) {
        close_current_page_init();
        Stage stage = (Stage) splitPane.getScene().getWindow();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("home"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Scene scene = new Scene(fx);
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    @FXML
    public void initialize() {
        init();
        listView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                boolean flag = false;

                if (newValue.getIndex() == 0) {
                    if (video != null) {
                        flag = true;
                    }
                    video(flag);
                }
                if (newValue.getIndex() == 1) {
                    if (music != null) {
                        flag = true;
                    }
                    music(flag);
                }
                if (newValue.getIndex() == 2) {
                    if (vip_parser != null) {
                        flag = true;
                    }
                    vip_parser(flag);
                }

                if (newValue.getIndex() == 3) {
                    if (music_parser != null) {
                        flag = true;
                    }
                    music_parser(flag);
                }

                if (newValue.getIndex() == 4) {
                    if (video_transcoder != null) {
                        flag = true;
                    }
                    video_transcoder(flag);
                }
            }
        });
    }

    public static Image getImage(ResourcesUtils.Player player) {
        return switch (player) {
            case Video -> new Image(ImagePath.path(ImagePath.ImagePathType.VIDEO_PLAYER));
            case Music -> new Image(ImagePath.path(ImagePath.ImagePathType.MUSIC_PLAYER));
            case VipParser -> new Image(ImagePath.path(ImagePath.ImagePathType.VIP_PLAYER));
            case MusicParser -> new Image("image/music_vip.png");
            case VideoTranscoder -> new Image("image/video_tr.png");
        };
    }

    public void init() {
        ResourcesUtils.Player[] values = ResourcesUtils.Player.values();
        ObservableList<ResourcesUtils.Player> list = FXCollections.observableArrayList();
        list.addAll(Arrays.asList(values));
        listView.setItems(list);
        listView.setFixedCellSize(40);
        listView.setCellFactory(new Callback<>() {

            private int position;

            @Override
            public ListCell<ResourcesUtils.Player> call(ListView<ResourcesUtils.Player> playerListView) {

                Label label = new Label();
                label.setPrefWidth(200);
                ListCell<ResourcesUtils.Player> listCell = new ListCell<>() {
                    @Override
                    protected void updateItem(ResourcesUtils.Player player, boolean b) {
                        super.updateItem(player, b);
                        if (!b) {
                            HBox hBox = new HBox(30);
                            hBox.setAlignment(Pos.CENTER);
                            label.setText(player.getTitle());
                            label.setTextFill(Paint.valueOf("#000000"));
                            Image im = getImage(player);
                            ImageView iv = new ImageView(im);
                            iv.setPreserveRatio(true);
                            iv.setFitWidth(15);
                            hBox.getChildren().add(iv);
                            hBox.getChildren().add(label);
                            this.setGraphic(hBox);
                        }
                        this.setStyle("-fx-background-color: " + color_cell);
                    }
                };

                listCell.hoverProperty().addListener(new ChangeListener<Boolean>() {
                    @Override
                    public void changed(ObservableValue<? extends Boolean> observableValue, Boolean aBoolean, Boolean t1) {
                        if (t1 && !label.getText().equals("")) {
                            position = playerListView.getItems().indexOf(label.getText());
                            label.setFont(new Font(16));
                            playerListView.getFocusModel().focus(position);
                            listCell.setStyle("-fx-background-color: #369e7d");
                        } else {
                            label.setPrefHeight(20);
                            label.setFont(new Font(13));
                            listCell.setStyle("-fx-background-color: " + color_cell);
                        }
                    }
                });

                return listCell;
            }
        });
        video(false);
    }

    private void music(boolean flag) {
        listView.getSelectionModel().select(1);
        if (!flag) {
            if (Constants.getRoot(Constants.Type.Music) != null){
                root = Constants.getRoot(Constants.Type.Music);
                music = root;
            }else {
                try {
                    FXMLLoader load = new FXMLLoader(ResourcesUtils.getResource("music"));
                    root = load.load();
                    musicController = load.getController();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                music = root;
            }
        } else {
            root = music;
        }
        common_method();
    }

    //视频转码
    private void video_transcoder(boolean flag) {
        listView.getSelectionModel().select(4);
        if (!flag) {
            if (Constants.getRoot(Constants.Type.VideoTranscoder) != null){
                root = Constants.getRoot(Constants.Type.VideoTranscoder);
                video_transcoder = root;
            }else {
                try {
                    FXMLLoader load = new FXMLLoader(ResourcesUtils.getResource("video-transcoder"));
                    root = load.load();
                    videoTranscoderController = load.getController();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                video_transcoder = root;
            }
        } else {
            root = video_transcoder;
        }
        common_method();
    }

    private void vip_parser(boolean flag) {
        listView.getSelectionModel().select(2);

        if (!flag) {
            try {
                root = FXMLLoader.load(ResourcesUtils.getResource("vip-parser"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            vip_parser = root;
        } else {
            root = vip_parser;
        }
        common_method();
    }

    private void music_parser(boolean flag) {
        listView.getSelectionModel().select(3);

        if (!flag) {
            try {
                root = FXMLLoader.load(ResourcesUtils.getResource("music-download"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            music_parser = root;
        } else {
            root = music_parser;
        }
        common_method();
    }

    private void video(boolean flag) {
        //默认选择第一个
        listView.getSelectionModel().select(0);

        if (!flag) {
            try {
//            root = FXMLLoader.load(ResourcesUtils.getResource("video"));
                FXMLLoader load = new FXMLLoader(ResourcesUtils.getResource("video"));
                root = load.load();
                videoController = load.getController();
            } catch (IOException e) {
                e.printStackTrace();
            }
            video = root;
        } else {
            root = video;
        }
        common_method();
    }


    private void common_method() {
        splitPane.getItems().remove(1);
        splitPane.getItems().add(1, root);
        root.widthProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                double width = splitPane.getWidth();
                PlayerController.this.width.set(width);
                log.info("player:--->width:{}", width);
            }
        });
        root.heightProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue != null) {
                double height = splitPane.getHeight();
                PlayerController.this.height.set(height);
                log.info("player:--->height:{}", height);
            }
        });

        this.width.addListener((observable, oldValue, newValue) -> {
            PlayerController.this.root.setPrefWidth(newValue.doubleValue() - listView.getWidth());
            log.info("newValue.doubleValue():{}", newValue.doubleValue());
        });

        this.height.addListener((observable, oldValue, newValue) -> {
            PlayerController.this.root.setPrefHeight(newValue.doubleValue());
            log.info("newValue.doubleValue():{}", newValue.doubleValue());
        });

    }

    @FXML
    public void http_request_menu_item(ActionEvent event) {
        load_http_tools(0);
    }

    @FXML
    public void http_upload_menu_item(ActionEvent event) {
        load_http_tools(1);
    }

    @FXML
    public void http_download_menu_item(ActionEvent event) {
        load_http_tools(2);
    }

    public void load_http_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("http-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    @FXML
    public void http_server_menu_item(ActionEvent event) {
        load_server_tools(0);
    }

    @FXML
    public void ftp_server_menu_item(ActionEvent event) {
        load_server_tools(1);
    }

    @FXML
    public void ssh_client_menu_item(ActionEvent event) {
        load_server_tools(2);
    }

    public void load_server_tools(int index) {
        close_current_page_init();
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("server-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void mail_menu_item(ActionEvent event) {
        load_small_tools(7);
    }

    public void socket_server_menu_item(ActionEvent event) {
        load_server_tools(3);
    }

    public void telephone_menu_item(ActionEvent event) {
        load_small_tools(8);
    }

    public void mybatis_plus_gen_menu_item(ActionEvent event) {
        load_sql_tools(1);
    }

    public void JsonView_menu_item(ActionEvent event) {
        load_small_tools(9);
    }

    public void maven_jar_install_menu_item(ActionEvent event) {
        load_small_tools(10);
    }

    public void jks_file_menu_item(ActionEvent event) {
        load_encrypt(3);
    }

    public void music_parser_menu_item(ActionEvent event) {
        boolean flag = false;
        if (music_parser != null) {
            flag = true;
        }
        music_parser(flag);
    }

    public void word_ocr_menu_item(ActionEvent event) {
        load_small_tools(11);
    }

    public void bar_code_menu_item(ActionEvent event) {
        load_small_tools(12);
    }

    public void pdf_menu_item(ActionEvent event) {
        load_small_tools(13);
    }

    public void batch_update_file_name_menu_item(ActionEvent event) {
        load_small_tools(14);
    }

    public void capter_screen_menu_item(ActionEvent event) {
        load_small_tools(15);
    }

    public void json_javabean_gen_menu_item(ActionEvent event) {
        load_sql_tools(2);
    }

    public void sql_query_gen_menu_item(ActionEvent event) {
        load_sql_tools(3);
    }

    public void socket_client_aio_menu_item(ActionEvent event) {
        load_server_tools(4);
    }

    public void socket_server_aio_menu_item(ActionEvent event) {
        load_server_tools(5);
    }

    public void socket_server_nio_menu_item(ActionEvent event) {
        load_server_tools(6);
    }

    public void socket_client_nio_menu_item(ActionEvent event) {
        load_server_tools(7);
    }

    public void video_transcoder_menu_item(ActionEvent event) {
        boolean flag = false;
        if (video_transcoder != null){
            flag = true;
        }
        video_transcoder(flag);
    }

    public void file_edit_menu_item(ActionEvent actionEvent) {
        load_small_tools(16);
    }

    public void layui_form_gen_menu_item(ActionEvent actionEvent) {
        load_small_tools(17);
    }

    public void log_console_menu_item(ActionEvent actionEvent) {
        load_small_tools(18);
    }

    public void edit_plus_code_menu_item(ActionEvent actionEvent) {
        load_small_tools(19);
    }

    public void minio_upload_menu_item(ActionEvent actionEvent) {
        load_small_tools(20);
    }

    public void excel_read_menu_item(ActionEvent actionEvent) {
        load_small_tools(21);
    }

    public void web_socket_client_menu_item(ActionEvent actionEvent) {
        load_server_tools(8);
    }

    public void load_go_tools(int index){
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("go-tools"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }


    public void json_to_struct_menu_item(ActionEvent actionEvent) {
        load_go_tools(0);
    }

    public void mysql_to_struct_menu_item(ActionEvent actionEvent) {
        load_go_tools(1);
    }

    public void js_edit_list(int index){
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("editor-list"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void ace_js_menu_item(ActionEvent actionEvent) {
        js_edit_list(0);
    }

    public void monaco_js_menu_item(ActionEvent actionEvent) {
        js_edit_list(1);
    }

    public void codemirror_js_menu_item(ActionEvent actionEvent) {
        js_edit_list(2);
    }

    public void timeFx_fx_menu_item(ActionEvent actionEvent) {
        js_edit_list(3);
    }

    public void swing_menu_item(ActionEvent actionEvent) {
        js_edit_list(4);
    }

    public void js_edit_list_impl(int index){
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("editor-list-impl"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

//        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
//        listView.getSelectionModel().select(index);
    }

    public void ace_menu_item(ActionEvent actionEvent) {
        js_edit_list_impl(0);
    }

    public void load_chat_app(int index){
        AnchorPane fx = null;
        try {
            fx = FXMLLoader.load(ResourcesUtils.getResource("chat-app"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Scene scene = new Scene(fx);
        Stage stage = (Stage) splitPane.getScene().getWindow();
        stage.setScene(scene);

        ListView<ResourcesUtils.Player> listView = (ListView) fx.lookup("#listView");
        listView.getSelectionModel().select(index);
    }

    public void chat_app_menu_item(ActionEvent actionEvent) {
        load_chat_app(0);
    }
}
